// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_ERROR_CODE_HPP_
#define _XBASE_ERROR_CODE_HPP_

#include <ostream>

#include <boost/system/error_code.hpp>

namespace xbase
{
	namespace error
	{
		enum error_code
		{
			ok = 0,
			eos,		   // 扫描结束标志
			table_not_exists,  // 查询的表不存在
			tablet_not_exists, // 查询的子表不存在
			tablet_closed,	   // 子表处于关闭状态

			table_already_exists, // 创建的表已存在
			write_tablet_error,   // 写子表失败
			family_not_exists,    // 列族不存在
			group_not_exists,     // 组不存在
			scanner_not_exists, // 表示scanner id不存在，可能是没创建或超时

			column_name_with_regexp, // 列名包含正则表达式
			bad_table_struct,	 // 表结构不正确
			header_incomplete,	 // 头部不完整
			bad_magic,		 // magic错误
			packet_incomplete,	 // 包不完整

			packet_encode_failed, // 包编码失败
			packet_decode_failed, // 包解码失败
			duplicated_id,	      // id重复
			bad_packet_type,      // 包类型出错
			bad_row_name,	      // 行名为空
			
			empty_column_name,    // 列名为空
			empty_qualifier_name, // 小列名为空
			table_name_mismatch,
			bad_column_name, // 列名不正确，通常是没有冒号
			bad_meta_data_row,	// 该行不是元数据行

			row_not_in_range, // 行不在范围内，通常是指子表的行范围
			memtable_too_huge, // 内存表太大
			log_failed,	   // 记日志失败
			bad_address,	   // address 错误
			bad_table_name,	   // 表名不合法

			busying_module, // 模块正忙，不能处理新的异步请求
			group_already_exists,
			family_already_exists,
			bad_option,
			bad_table_info,

			root_meta_not_loaded,	// 根子表未载入
			no_tablet_loaded,		// 某个表没有子表载入
			service_stopped,
			write_table_info_file_failed,	// 写表信息文件失败
			invalid_table_struct,		// 无效的表结构
			
			// ...

			error_code_end
		};

		static
		const char * error_string[] = {
			"ok",
			"end of scanner",
			"table not exists",
			"tablet not exists",
			"tablet closed",

			"table already exists",
			"write tablet error",
			"family not exists",
			"group not exists",
			"scanner not exists",

			"column name with regexp",
			"bad table struct",
			"header incomplete",
			"magic invalid",
			"packet incomplete",
			
			"packet encode failed",
			"packet decode failed",
			"duplicated id",
			"bad packet type",
			"bad row name",

			"empty column name",
			"empty qualifier name",
			"table name mismatch",
			"bad column name",
			"bad meta data row",

			"row not in range",
			"memtable too huge",
			"log failed",
			"bad address",
			"bad table name",

			"busying module",
			"group already exists",
			"family already exists",
			"bad option",
			"bad table info",

			"root meta not loaded",
			"no tablet loaded",
			"service stopped",

			// ...
			
			"unknown error"
		};

		inline
		const char * get_error_string(int value)
		{
			const error_code ec = static_cast<error_code>(value);
			return error_string[
				((ec < error_code_end)
				 ? ec
				 : error_code_end)
				];
		}

		static const char * const s_name = "xbase";

		template <typename charT, typename traits>
		inline
		std::basic_ostream<charT,traits>&
		operator<< (std::basic_ostream<charT,traits>& out, error_code ec)
		{
			out << s_name
			    << ':' << (unsigned int)ec << " - "
			    << get_error_string(ec);
			return out;
		}

		namespace detail
		{
			struct error_category
				: public boost::system::error_category
			{
				const char *name() const {
					return s_name;
				}
					
				std::string message(int value) const {
					return get_error_string(value);
				}
			};
		} // namespace detail

		// 注意：
		// 不要声明为static!，否则会使s_instance实例为多个（即
		// 每个.o文件中一个），导致不同.o文件中错误码比较的时候
		// 会出错！
		inline
		const boost::system::error_category &get_error_category()
		{
			static const detail::error_category s_instance;
			return s_instance;
		}
			
		static const
		boost::system::error_category &error_category = get_error_category();
			
	} // namespace error

} // namespace xbase

namespace boost
{
	namespace system
	{
		template<>
		struct is_error_code_enum<xbase::error::error_code>
		{
			static const bool value = true;
		};
	} // namespace system
	
} // namespace boost

namespace xbase
{
	namespace error
	{
		inline
		boost::system::error_code make_error_code(error_code ec)
		{
			return boost::system::error_code(ec,
							 error_category);
		}
	} // namespace error

} // namespace xbase

#endif	// _XBASE_ERROR_CODE_HPP_
